//
//  DataBaseHandle.m
//  UI20_数据库
//
//  Created by 韩震明 on 15/10/14.
//  Copyright © 2015年 韩震明. All rights reserved.
//

#import "DataBaseHandle.h"

@implementation DataBaseHandle

+ (instancetype)sharDataVaseHandle
{
    static DataBaseHandle *handle;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        handle = [[DataBaseHandle alloc] init];
        
    });
    return handle;
}

- (void)openDb
{
    
    // 数据库的文件保存在本地的沙盒路径,所以打开数据库先得根据路径找数据库的文件
    NSString *sandBoxPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    // 拼接一个数据库文件路径,如果路径下没有这个数据库文件则会创建一个,如果有的话,不重复创建,直接打开数据库
    NSString *dbPath = [sandBoxPath stringByAppendingPathComponent:@"collection.sqlite"];
    // 为了让数据库工具能代开数据库的文件,一般文件的扩展名是sqlite或者db,其他的打不开
    
    // 打开数据库
    // 参数1:文件的路径,需要把OC的字符串转换成C语言的字符串
    // 调用的语句会返回执行结果,每个数字代表了不同的情况,如果发现错误,可以打印result,对照错误,修改
    int result = sqlite3_open([dbPath UTF8String], &dbPoint);
    if (result == SQLITE_OK) {
        NSLog(@"开启成功");
    } else {
        NSLog(@"开启失败");
    }
    NSLog(@"%d", result);
}

- (void)createTable
{
    // 数据库问题80%是sql语句写错了,所以先用工具测试sql语句写的是否正确,无误在粘贴到工程里
    NSString *sqlStr = @"create table if not exists topic(title text, pic text, likes text, cellId text, cellType text)";
    // 在数据库代开的情况下,直接操作sql语句的执行
    // 数据库打开就是对dbpoint的指针进行赋值
    int result = sqlite3_exec(dbPoint, [sqlStr UTF8String], nil, nil, nil);
    if (result == SQLITE_OK) {
        NSLog(@"创建表成功");
    } else {
        NSLog(@"创建表失败");
    }
}

- (void)insertStu:(SYSpecialTableViewModel *)topic
{
    NSString *sqlStr = [NSString stringWithFormat:@"insert into topic (title, pic, likes, cellId, cellType) values ('%@', '%@', '%@', '%@', '%@')", topic.title, topic.pic, topic.likes, topic.cellId, topic.cellType];
    int result = sqlite3_exec(dbPoint, [sqlStr UTF8String], nil, nil, nil);
    if (result == SQLITE_OK) {
        NSLog(@"超乳成功");
    } else {
        NSLog(@"超乳失败");
        NSLog(@"%d", result);
    }
}

- (void)deleteStu:(SYSpecialTableViewModel *)topic
{
    // 删除分两种,一种是物理删除,就是使用delete语句把数据全部删掉,另外一种是update这种是通过更改某个条件,在查找过程中找不到,但是数据内容还在
    NSString *sqlStr = [NSString stringWithFormat:@"delete from topic where title = '%@'", topic.title];
    int result = sqlite3_exec(dbPoint, [sqlStr UTF8String], nil, nil, nil);
    if (result == SQLITE_OK) {
        NSLog(@"删除成功");
    } else {
        NSLog(@"删除失败");
        NSLog(@"%d", result);
    }
}

- (void)UpDataStu:(SYSpecialTableViewModel *)topic
{
//    NSString *sqlStr = [NSString stringWithFormat:@"update stu set name = 'laomao', sex = 'nan', age = 15 where title = '%@'", topic.title];
//    // 主键不能更新
//    // 执行sql语句
//    int result = sqlite3_exec(dbPoint, [sqlStr UTF8String], nil, nil, nil);
//    if (result == SQLITE_OK) {
//        NSLog(@"更新成功");
//    } else {
//        NSLog(@"更新失败");
//    }
}


- (NSMutableArray *)selectTopic
{
    // 查询的逻辑
    // 1.先从本地的数据库里读取出来所有需要的数据
    // 2.然后把读出来的数据逐条给model的属性进行赋值
    // 3.最后把赋值好的model放到数组里返回
    NSString *sqlStr = [NSString stringWithFormat:@"select * from topic"];
    // *是通配符的意思,它代表了查询所有的字段内容,如果想查询特定字段,把*换成字段名
    
    // 接下来需要创建一个跟随指针,用来遍历数据库里传出来的每一条数据
    sqlite3_stmt *stmt = nil;
    
    // 进行查询
    // 第三个参数:查询语句字数的限制,-1是没有限制
    int result = sqlite3_prepare_v2(dbPoint, [sqlStr UTF8String], -1, &stmt, nil);
    // 这个方法相当于把数据库,跟随指针,sql关联在一起,共同执行
    NSMutableArray *topicArr = [NSMutableArray array];
    if (result == SQLITE_OK) {
        // 逐行进行遍历
        // 如果当前行没有数据了,循环结束,整个遍历过程结束
        while (sqlite3_step(stmt) == SQLITE_ROW) {
            // 满足循环条件,开始逐个model进行赋值
            const unsigned char *title = sqlite3_column_text(stmt, 0);
            const unsigned char *pic = sqlite3_column_text(stmt, 1);
            const unsigned char *likes = sqlite3_column_text(stmt, 2);
            const unsigned char *cellId = sqlite3_column_text(stmt, 3);
            const unsigned char *cellType = sqlite3_column_text(stmt, 4);
            // 把数据的类型进行转换
            SYSpecialTableViewModel *topic = [[SYSpecialTableViewModel alloc] init];
            topic.title = [NSString stringWithUTF8String:(const char *)title];
            topic.pic = [NSString stringWithUTF8String:(const char *)pic];
            topic.likes = [NSString stringWithUTF8String:(const char *) likes];
            topic.cellId = [NSString stringWithUTF8String:(const char *) cellId];
            topic.cellType = [NSString stringWithUTF8String:(const char *) cellType];
            
            [topicArr addObject:topic];
        }
    }
    // 把跟随指针注销掉,如果不注销掉,多次查找之后会返回5,数据库繁忙,所以每次查询之后要注销
    sqlite3_finalize(stmt);
    
    return topicArr;
}

// 查询
- (SelectSuper)isHaveInTable:(SYSpecialTableViewModel *)topic
{
    //      除了openDB, 都先写SQL语句
    
    NSString *sqlStr = [NSString stringWithFormat:@"select * from topic where title = '%@'", topic.title];
    
    //    NSLog(@"%@", sup.title);
    
    //      跟随指针
    sqlite3_stmt *stmt = nil;
    
    //      执行SQL语句
    int result = sqlite3_prepare_v2(dbPoint, [sqlStr UTF8String], -1, &stmt, nil);
    
    if (result == SQLITE_OK) {
        
        NSLog(@"查询成功");
        if (sqlite3_step(stmt) == SQLITE_ROW) {
            
            sqlite3_finalize(stmt);
            return InTable;
        } else {
            
            sqlite3_finalize(stmt);
            return NotInTable;
        }
    } else {
        
        sqlite3_finalize(stmt);
        NSLog(@"查询失败");
        return SelectError;
    }
    
    return YES;
}
/*****************************/

- (void)closeDB
{
    int result = sqlite3_close(dbPoint);
    if (result == SQLITE_OK) {
        dbPoint = nil;
    }
}

@end

























